from rest_framework import serializers

from books.models import BookInfo


# 1.
class BookInfoSerializer(serializers.ModelSerializer):
    """图书数据序列化器"""

    class Meta:
        # model指明该序列化器处理的数据字段从模型类BookInfo参考⽣成
        model = BookInfo
        # fileds指明该序列化器包含模型类中的哪些字段，'__all__'指明包含所有字段
        fields = '__all__'


# 验证第三种： 在字段中添加validators选项参数，也可以补充验证⾏为(shell使用)，
def about_django(value):
    if 'django' not in value.lower():
        raise serializers.ValidationError("图书不是关于Django的")


# 在django shell中来学习序列化器的使⽤--1。
# 为模型类定义一个序列化器(在shell环境下使用)
class BookInfoSerializerTest(serializers.Serializer):
    """图书数据序列化器"""
    id = serializers.IntegerField(label='ID', read_only=True)
    btitle = serializers.CharField(label='名称', max_length=20, validators=[about_django])
    bpub_date = serializers.DateField(label='发布⽇期', required=False)
    bread = serializers.IntegerField(label='阅读量', required=False)
    bcomment = serializers.IntegerField(label='评论量', required=False)
    image = serializers.ImageField(label='图⽚', required=False)
    # 如果关联的对象数据不是只有⼀个，⽽是包含多个数据，如想序列化图书BookInfo数据，每个
    # BookInfo对象关联的英雄HeroInfo对象可能有多个,多补充⼀个many=True参数
    # heroinfo_set=serializers.PrimaryKeyRelatedField(read_only=True,many=True)

    # 返回字符串,read_only=True序列化输出
    heroinfo_set = serializers.StringRelatedField(read_only=True, many=True)

    # < field_name > 字段进⾏验证
    # validate_ < field_name >验证:第一种

    # def validate_btitle(self, value):
    #     if 'django' not in value.lower():
    #         raise serializers.ValidationError("图书不是关于Django的")
    #
    #     return value

    # 在序列化器中需要同时对多个字段进⾏⽐较验证时，可以定义validate⽅法来验证
    # 验证:第二种

    # def validate(self, attrs):
    #     bread = attrs['bread']
    #
    #     bcomment = attrs['bcomment']
    #     if bread < bcomment:
    #         raise serializers.ValidationError('阅读量⼩于评论量')
    #     return attrs


# 1）⽤于序列化时，将模型类对象传⼊instance参数
# 2）⽤于反序列化时，将要被反序列化的数据传⼊data参数

# 先查询出⼀个图书对象--1.1
# from books.serializers import BookInfoSerializer
# from books.models import BookInfo
#
# # 构造序列化器对象--1.2
# bs = BookInfoSerializerTest(instance=BookInfo.objects.get(id=1))
#
# # 获取序列化数据--1.3
# bs.data
#
# # 如果要被序列化的是包含多条数据的查询集QuerySet，
# # 可以通过添加many=True参数补充说明--1.4
# books = BookInfo.objects.all()
# books = BookInfoSerializerTest(instance=books, many=True)
# books.data


class HeroInfoSerializer(serializers.Serializer):
    """英雄数据序列化器"""
    GENDER_CHOICES = (
        (0, 'male'),
        (1, 'female')
    )
    id = serializers.IntegerField(label='ID', read_only=True)
    hname = serializers.CharField(label='名字', max_length=20)
    hgender = serializers.ChoiceField(choices=GENDER_CHOICES, label='性别', required=
    False)
    hcomment = serializers.CharField(label='描述信息', max_length=200, required=False
                                     , allow_null=True)
    # 关联对象嵌套序列化
    # 第一种:关联书籍
    # hbook = serializers.PrimaryKeyRelatedField(label='图书', read_only=True)
    # 第二种: StringRelatedField此字段将被序列化为关联对象的字符串表示⽅式（即__str__⽅法的返回值）
    # hbook=serializers.StringRelatedField(label='图书')
    # 第三种:使⽤关联对象的序列化器
    hbook = BookInfoSerializerTest()


#
# # 反序列化使用(shell中使用)
# from books.serializers import BookInfoSerializerTest, HeroInfoSerializer
# from books.models import BookInfo, HeroInfo
#
# data = {
#     'btitle': ''
# }
# # 创建一个对象
# bs = BookInfoSerializerTest(data=data)
# bs.is_valid()
# # 错误信息显示
# bs.errors
#
# # s_valid()⽅法还可以在验证失败时抛出异常serializers.ValidationError，可以通过传
# # 递raise_exception=True参数开启，REST framework接收到此异常
# # serializer.is_valid(raise_exception=True)
#
# # 赋值后信息查看
# bs.validated_data


# 创建图书序列化--根据不同的使用场景创建不同的序列化对象
#  普通用户
class BookInfoSerializer1(serializers.Serializer):
    # id = serializers.IntegerField(label='ID')
    bpub_date = serializers.DateField(label='发布日期')
    bread = serializers.IntegerField(label="阅读量")
    bcomment = serializers.IntegerField(label='评论量')
    # is_delete = serializers.BooleanField(label="删除")
    image = serializers.ImageField(label='图片')


#  普通管理员
class BookInfoSerializer2(serializers.Serializer):
    id = serializers.IntegerField(label='ID')
    # bpub_date = serializers.DateField(label='发布日期')
    # bread = serializers.IntegerField(label="阅读量")
    bcomment = serializers.IntegerField(label='评论量')
    # is_delete = serializers.BooleanField(label="删除")
    image = serializers.ImageField(label='图片')


#  超级管理员
class BookInfoSerializer3(serializers.Serializer):
    id = serializers.IntegerField(label='ID')
    bpub_date = serializers.DateField(label='发布日期')
    bread = serializers.IntegerField(label="阅读量")
    bcomment = serializers.IntegerField(label='评论量')
    is_delete = serializers.BooleanField(label="删除")
    image = serializers.ImageField(label='图片')

    # 查询多的数据(返回的是英雄的id列表)，需要添加many=True
    # heroinfo_set=serializers.PrimaryKeyRelatedField(label='书籍中的英雄',read_only=True,many=True)
    # 返回的英雄对象名字的列表
    heroinfo_set=serializers.StringRelatedField(label='书籍中的英雄',many=True)


# 创建英雄序列化器
class HeroInfoSerializer1(serializers.Serializer):
    id = serializers.IntegerField(label="ID")
    hname = serializers.CharField(label="姓名")
    hgender = serializers.IntegerField(label="性别")
    hcomment = serializers.CharField(label="介绍")
    is_delete = serializers.BooleanField(label="删除")
    # 第一种：返回的是关联对象的id
    # hbook = serializers.PrimaryKeyRelatedField(label='所在书籍', read_only=True)
    # 第二种：返回的是 对象.__str__()
    # hbook = serializers.StringRelatedField(label="所在书籍名字")
    # 第三种：不需要传递instance参数
    # 但会的是 BookInfoSerializer3(hero.hbook).data
    hbook = BookInfoSerializer3()


# 英雄序列器定义
class HeroInfoSerializer2(serializers.Serializer):
    id = serializers.IntegerField(label="ID")
    hname = serializers.CharField(label="姓名")
    hgender = serializers.IntegerField(label="性别")
    hcomment = serializers.CharField(label="介绍")
    # is_delete = serializers.BooleanField(label="删除")
    # hbook = serializers.PrimaryKeyRelatedField(label='所在书籍', read_only=True)ers.PrimaryKeyRelatedField(label='所在书籍',read_only=True)
